home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Freeware 2002 November
/
SGI Freeware 2002 November - Disc 1.iso
/
dist
/
fw_emacs-lisp-intro.idb
/
usr
/
freeware
/
info
/
emacs-lisp-intro.info-5.z
/
emacs-lisp-intro.info-5
Wrap
Text File
|
2002-07-08
|
50KB
|
1,260 lines
This is emacs-lisp-intro.info, produced by makeinfo version 4.0b from
emacs-lisp-intro.texi.
INFO-DIR-SECTION Emacs
START-INFO-DIR-ENTRY
* Emacs Lisp Intro: (eintr).
A simple introduction to Emacs Lisp programming.
END-INFO-DIR-ENTRY
This is an introduction to `Programming in Emacs Lisp', for people
who are not programmers.
Edition 2.04, 2001 Dec 17
Copyright (C) 1990, '91, '92, '93, '94, '95, '97, 2001 Free Software
Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with the
Invariant Section being the Preface, with the Front-Cover Texts being
no Front-Cover Texts, and with the Back-Cover Texts being no Back-Cover
Texts. A copy of the license is included in the section entitled "GNU
Free Documentation License".
File: emacs-lisp-intro.info, Node: if & or, Next: Insert or, Prev: insert-buffer body, Up: insert-buffer
`insert-buffer' With an `if' Instead of an `or'
-----------------------------------------------
The job to be done is to make sure the value of `buffer' is a buffer
itself and not the name of a buffer. If the value is the name, then
the buffer itself must be got.
You can imagine yourself at a conference where an usher is wandering
around holding a list with your name on it and looking for you: the
usher is "bound" to your name, not to you; but when the usher finds you
and takes your arm, the usher becomes "bound" to you.
In Lisp, you might describe this situation like this:
(if (not (holding-on-to-guest))
(find-and-take-arm-of-guest))
We want to do the same thing with a buffer--if we do not have the
buffer itself, we want to get it.
Using a predicate called `bufferp' that tells us whether we have a
buffer (rather than its name), we can write the code like this:
(if (not (bufferp buffer)) ; if-part
(setq buffer (get-buffer buffer))) ; then-part
Here, the true-or-false-test of the `if' expression is
`(not (bufferp buffer))'; and the then-part is the expression
`(setq buffer (get-buffer buffer))'.
In the test, the function `bufferp' returns true if its argument is
a buffer--but false if its argument is the name of the buffer. (The
last character of the function name `bufferp' is the character `p'; as
we saw earlier, such use of `p' is a convention that indicates that the
function is a predicate, which is a term that means that the function
will determine whether some property is true or false. *Note Using the
Wrong Type Object as an Argument: Wrong Type of Argument.)
The function `not' precedes the expression `(bufferp buffer)', so
the true-or-false-test looks like this:
(not (bufferp buffer))
`not' is a function that returns true if its argument is false and
false if its argument is true. So if `(bufferp buffer)' returns true,
the `not' expression returns false and vice-versa: what is "not true"
is false and what is "not false" is true.
Using this test, the `if' expression works as follows: when the
value of the variable `buffer' is actually a buffer rather then its
name, the true-or-false-test returns false and the `if' expression does
not evaluate the then-part. This is fine, since we do not need to do
anything to the variable `buffer' if it really is a buffer.
On the other hand, when the value of `buffer' is not a buffer
itself, but the name of a buffer, the true-or-false-test returns true
and the then-part of the expression is evaluated. In this case, the
then-part is `(setq buffer (get-buffer buffer))'. This expression uses
the `get-buffer' function to return an actual buffer itself, given its
name. The `setq' then sets the variable `buffer' to the value of the
buffer itself, replacing its previous value (which was the name of the
buffer).
File: emacs-lisp-intro.info, Node: Insert or, Next: Insert let, Prev: if & or, Up: insert-buffer
The `or' in the Body
--------------------
The purpose of the `or' expression in the `insert-buffer' function
is to ensure that the argument `buffer' is bound to a buffer and not
just to the name of a buffer. The previous section shows how the job
could have been done using an `if' expression. However, the
`insert-buffer' function actually uses `or'. To understand this, it is
necessary to understand how `or' works.
An `or' function can have any number of arguments. It evaluates
each argument in turn and returns the value of the first of its
arguments that is not `nil'. Also, and this is a crucial feature of
`or', it does not evaluate any subsequent arguments after returning the
first non-`nil' value.
The `or' expression looks like this:
(or (bufferp buffer)
(setq buffer (get-buffer buffer)))
The first argument to `or' is the expression `(bufferp buffer)'. This
expression returns true (a non-`nil' value) if the buffer is actually a
buffer, and not just the name of a buffer. In the `or' expression, if
this is the case, the `or' expression returns this true value and does
not evaluate the next expression--and this is fine with us, since we do
not want to do anything to the value of `buffer' if it really is a
buffer.
On the other hand, if the value of `(bufferp buffer)' is `nil',
which it will be if the value of `buffer' is the name of a buffer, the
Lisp interpreter evaluates the next element of the `or' expression.
This is the expression `(setq buffer (get-buffer buffer))'. This
expression returns a non-`nil' value, which is the value to which it
sets the variable `buffer'--and this value is a buffer itself, not the
name of a buffer.
The result of all this is that the symbol `buffer' is always bound
to a buffer itself rather than to the name of a buffer. All this is
necessary because the `set-buffer' function in a following line only
works with a buffer itself, not with the name to a buffer.
Incidentally, using `or', the situation with the usher would be
written like this:
(or (holding-on-to-guest) (find-and-take-arm-of-guest))
File: emacs-lisp-intro.info, Node: Insert let, Prev: Insert or, Up: insert-buffer
The `let' Expression in `insert-buffer'
---------------------------------------
After ensuring that the variable `buffer' refers to a buffer itself
and not just to the name of a buffer, the `insert-buffer function'
continues with a `let' expression. This specifies three local
variables, `start', `end', and `newmark' and binds them to the initial
value `nil'. These variables are used inside the remainder of the
`let' and temporarily hide any other occurrence of variables of the
same name in Emacs until the end of the `let'.
The body of the `let' contains two `save-excursion' expressions.
First, we will look at the inner `save-excursion' expression in detail.
The expression looks like this:
(save-excursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
The expression `(set-buffer buffer)' changes Emacs' attention from the
current buffer to the one from which the text will copied. In that
buffer, the variables `start' and `end' are set to the beginning and
end of the buffer, using the commands `point-min' and `point-max'.
Note that we have here an illustration of how `setq' is able to set two
variables in the same expression. The first argument of `setq' is set
to the value of its second, and its third argument is set to the value
of its fourth.
After the body of the inner `save-excursion' is evaluated, the
`save-excursion' restores the original buffer, but `start' and `end'
remain set to the values of the beginning and end of the buffer from
which the text will be copied.
The outer `save-excursion' expression looks like this:
(save-excursion
(INNER-`save-excursion'-EXPRESSION
(GO-TO-NEW-BUFFER-AND-SET-`start'-AND-`end')
(insert-buffer-substring buffer start end)
(setq newmark (point)))
The `insert-buffer-substring' function copies the text _into_ the
current buffer _from_ the region indicated by `start' and `end' in
`buffer'. Since the whole of the second buffer lies between `start'
and `end', the whole of the second buffer is copied into the buffer you
are editing. Next, the value of point, which will be at the end of the
inserted text, is recorded in the variable `newmark'.
After the body of the outer `save-excursion' is evaluated, point and
mark are relocated to their original places.
However, it is convenient to locate a mark at the end of the newly
inserted text and locate point at its beginning. The `newmark'
variable records the end of the inserted text. In the last line of the
`let' expression, the `(push-mark newmark)' expression function sets a
mark to this location. (The previous location of the mark is still
accessible; it is recorded on the mark ring and you can go back to it
with `C-u C-<SPC>'.) Meanwhile, point is located at the beginning of
the inserted text, which is where it was before you called the insert
function.
The whole `let' expression looks like this:
(let (start end newmark)
(save-excursion
(save-excursion
(set-buffer buffer)
(setq start (point-min) end (point-max)))
(insert-buffer-substring buffer start end)
(setq newmark (point)))
(push-mark newmark))
Like the `append-to-buffer' function, the `insert-buffer' function
uses `let', `save-excursion', and `set-buffer'. In addition, the
function illustrates one way to use `or'. All these functions are
building blocks that we will find and use again and again.
File: emacs-lisp-intro.info, Node: beginning-of-buffer, Next: Second Buffer Related Review, Prev: insert-buffer, Up: More Complex
Complete Definition of `beginning-of-buffer'
============================================
The basic structure of the `beginning-of-buffer' function has
already been discussed. (*Note A Simplified `beginning-of-buffer'
Definition: simplified-beginning-of-buffer.) This section describes
the complex part of the definition.
As previously described, when invoked without an argument,
`beginning-of-buffer' moves the cursor to the beginning of the buffer,
leaving the mark at the previous position. However, when the command
is invoked with a number between one and ten, the function considers
that number to be a fraction of the length of the buffer, measured in
tenths, and Emacs moves the cursor that fraction of the way from the
beginning of the buffer. Thus, you can either call this function with
the key command `M-<', which will move the cursor to the beginning of
the buffer, or with a key command such as `C-u 7 M-<' which will move
the cursor to a point 70% of the way through the buffer. If a number
bigger than ten is used for the argument, it moves to the end of the
buffer.
The `beginning-of-buffer' function can be called with or without an
argument. The use of the argument is optional.
* Menu:
* Optional Arguments::
* beginning-of-buffer opt arg:: Example with optional argument.
* beginning-of-buffer complete::
File: emacs-lisp-intro.info, Node: Optional Arguments, Next: beginning-of-buffer opt arg, Prev: beginning-of-buffer, Up: beginning-of-buffer
Optional Arguments
------------------
Unless told otherwise, Lisp expects that a function with an argument
in its function definition will be called with a value for that
argument. If that does not happen, you get an error and a message that
says `Wrong number of arguments'.
However, optional arguments are a feature of Lisp: a "keyword" may
be used to tell the Lisp interpreter that an argument is optional. The
keyword is `&optional'. (The `&' in front of `optional' is part of the
keyword.) In a function definition, if an argument follows the keyword
`&optional', a value does not need to be passed to that argument when
the function is called.
The first line of the function definition of `beginning-of-buffer'
therefore looks like this:
(defun beginning-of-buffer (&optional arg)
In outline, the whole function looks like this:
(defun beginning-of-buffer (&optional arg)
"DOCUMENTATION..."
(interactive "P")
(push-mark)
(goto-char
(IF-THERE-IS-AN-ARGUMENT
FIGURE-OUT-WHERE-TO-GO
ELSE-GO-TO
(point-min))))
The function is similar to the `simplified-beginning-of-buffer'
function except that the `interactive' expression has `"P"' as an
argument and the `goto-char' function is followed by an if-then-else
expression that figures out where to put the cursor if there is an
argument.
The `"P"' in the `interactive' expression tells Emacs to pass a
prefix argument, if there is one, to the function. A prefix argument
is made by typing the <META> key followed by a number, or by typing
`C-u' and then a number (if you don't type a number, `C-u' defaults to
4).
The true-or-false-test of the `if' expression is simple: it is
simply the argument `arg'. If `arg' has a value that is not `nil',
which will be the case if `beginning-of-buffer' is called with an
argument, then this true-or-false-test will return true and the
then-part of the `if' expression will be evaluated. On the other hand,
if `beginning-of-buffer' is not called with an argument, the value of
`arg' will be `nil' and the else-part of the `if' expression will be
evaluated. The else-part is simply `point-min', and when this is the
outcome, the whole `goto-char' expression is `(goto-char (point-min))',
which is how we saw the `beginning-of-buffer' function in its simplified
form.
File: emacs-lisp-intro.info, Node: beginning-of-buffer opt arg, Next: beginning-of-buffer complete, Prev: Optional Arguments, Up: beginning-of-buffer
`beginning-of-buffer' with an Argument
--------------------------------------
When `beginning-of-buffer' is called with an argument, an expression
is evaluated which calculates what value to pass to `goto-char'. This
expression is rather complicated at first sight. It includes an inner
`if' expression and much arithmetic. It looks like this:
(if (> (buffer-size) 10000)
;; Avoid overflow for large buffer sizes!
(* (prefix-numeric-value arg) (/ (buffer-size) 10))
(/
(+ 10
(*
(buffer-size) (prefix-numeric-value arg))) 10))
* Menu:
* Disentangle beginning-of-buffer::
* Large buffer case::
* Small buffer case::
File: emacs-lisp-intro.info, Node: Disentangle beginning-of-buffer, Next: Large buffer case, Prev: beginning-of-buffer opt arg, Up: beginning-of-buffer opt arg
Disentangle `beginning-of-buffer'
.................................
Like other complex-looking expressions, the conditional expression
within `beginning-of-buffer' can be disentangled by looking at it as
parts of a template, in this case, the template for an if-then-else
expression. In skeletal form, the expression looks like this:
(if (BUFFER-IS-LARGE
DIVIDE-BUFFER-SIZE-BY-10-AND-MULTIPLY-BY-ARG
ELSE-USE-ALTERNATE-CALCULATION
The true-or-false-test of this inner `if' expression checks the size
of the buffer. The reason for this is that the old Version 18 Emacs
used numbers that are no bigger than eight million or so and in the
computation that followed, the programmer feared that Emacs might try
to use over-large numbers if the buffer were large. The term
`overflow', mentioned in the comment, means numbers that are over
large. Version 21 Emacs uses larger numbers, but this code has not
been touched, if only because people now look at buffers that are far,
far larger than ever before.
There are two cases: if the buffer is large and if it is not.
File: emacs-lisp-intro.info, Node: Large buffer case, Next: Small buffer case, Prev: Disentangle beginning-of-buffer, Up: beginning-of-buffer opt arg
What happens in a large buffer
..............................
In `beginning-of-buffer', the inner `if' expression tests whether
the size of the buffer is greater than 10,000 characters. To do this,
it uses the `>' function and the `buffer-size' function.
The line looks like this:
(if (> (buffer-size) 10000)
When the buffer is large, the then-part of the `if' expression is
evaluated. It reads like this (after formatting for easy reading):
(*
(prefix-numeric-value arg)
(/ (buffer-size) 10))
This expression is a multiplication, with two arguments to the function
`*'.
The first argument is `(prefix-numeric-value arg)'. When `"P"' is
used as the argument for `interactive', the value passed to the
function as its argument is passed a "raw prefix argument", and not a
number. (It is a number in a list.) To perform the arithmetic, a
conversion is necessary, and `prefix-numeric-value' does the job.
The second argument is `(/ (buffer-size) 10)'. This expression
divides the numeric value of the buffer by ten. This produces a number
that tells how many characters make up one tenth of the buffer size.
(In Lisp, `/' is used for division, just as `*' is used for
multiplication.)
In the multiplication expression as a whole, this amount is
multiplied by the value of the prefix argument--the multiplication
looks like this:
(* NUMERIC-VALUE-OF-PREFIX-ARG
NUMBER-OF-CHARACTERS-IN-ONE-TENTH-OF-THE-BUFFER)
If, for example, the prefix argument is `7', the one-tenth value will
be multiplied by 7 to give a position 70% of the way through the buffer.
The result of all this is that if the buffer is large, the
`goto-char' expression reads like this:
(goto-char (* (prefix-numeric-value arg)
(/ (buffer-size) 10)))
This puts the cursor where we want it.
File: emacs-lisp-intro.info, Node: Small buffer case, Prev: Large buffer case, Up: beginning-of-buffer opt arg
What happens in a small buffer
..............................
If the buffer contains fewer than 10,000 characters, a slightly
different computation is performed. You might think this is not
necessary, since the first computation could do the job. However, in a
small buffer, the first method may not put the cursor on exactly the
desired line; the second method does a better job.
The code looks like this:
(/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10))
This is code in which you figure out what happens by discovering how the
functions are embedded in parentheses. It is easier to read if you
reformat it with each expression indented more deeply than its
enclosing expression:
(/
(+ 10
(*
(buffer-size)
(prefix-numeric-value arg)))
10))
Looking at parentheses, we see that the innermost operation is
`(prefix-numeric-value arg)', which converts the raw argument to a
number. This number is multiplied by the buffer size in the following
expression:
(* (buffer-size) (prefix-numeric-value arg)
This multiplication creates a number that may be larger than the size of
the buffer--seven times larger if the argument is 7, for example. Ten
is then added to this number and finally the large number is divided by
ten to provide a value that is one character larger than the percentage
position in the buffer.
The number that results from all this is passed to `goto-char' and
the cursor is moved to that point.
File: emacs-lisp-intro.info, Node: beginning-of-buffer complete, Prev: beginning-of-buffer opt arg, Up: beginning-of-buffer
The Complete `beginning-of-buffer'
----------------------------------
Here is the complete text of the `beginning-of-buffer' function:
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer;
leave mark at previous position.
With arg N, put point N/10 of the way
from the true beginning.
Don't use this in Lisp programs!
\(goto-char (point-min)) is faster
and does not set the mark."
(interactive "P")
(push-mark)
(goto-char
(if arg
(if (> (buffer-size) 10000)
;; Avoid overflow for large buffer sizes!
(* (prefix-numeric-value arg)
(/ (buffer-size) 10))
(/ (+ 10 (* (buffer-size)
(prefix-numeric-value arg)))
10))
(point-min)))
(if arg (forward-line 1)))
Except for two small points, the previous discussion shows how this
function works. The first point deals with a detail in the
documentation string, and the second point concerns the last line of
the function.
In the documentation string, there is reference to an expression:
\(goto-char (point-min))
A `\' is used before the first parenthesis of this expression. This
`\' tells the Lisp interpreter that the expression should be printed as
shown in the documentation rather than evaluated as a symbolic
expression, which is what it looks like.
Finally, the last line of the `beginning-of-buffer' command says to
move point to the beginning of the next line if the command is invoked
with an argument:
(if arg (forward-line 1)))
This puts the cursor at the beginning of the first line after the
appropriate tenths position in the buffer. This is a flourish that
means that the cursor is always located _at least_ the requested tenths
of the way through the buffer, which is a nicety that is, perhaps, not
necessary, but which, if it did not occur, would be sure to draw
complaints.
File: emacs-lisp-intro.info, Node: Second Buffer Related Review, Next: optional Exercise, Prev: beginning-of-buffer, Up: More Complex
Review
======
Here is a brief summary of some of the topics covered in this
chapter.
`or'
Evaluate each argument in sequence, and return the value of the
first argument that is not `nil'; if none return a value that is
not `nil', return `nil'. In brief, return the first true value of
the arguments; return a true value if one _or_ any of the other
are true.
`and'
Evaluate each argument in sequence, and if any are `nil', return
`nil'; if none are `nil', return the value of the last argument.
In brief, return a true value only if all the arguments are true;
return a true value if one _and_ each of the others is true.
`&optional'
A keyword used to indicate that an argument to a function
definition is optional; this means that the function can be
evaluated without the argument, if desired.
`prefix-numeric-value'
Convert the `raw prefix argument' produced by `(interactive "P")'
to a numeric value.
`forward-line'
Move point forward to the beginning of the next line, or if the
argument is greater than one, forward that many lines. If it
can't move as far forward as it is supposed to, `forward-line'
goes forward as far as it can and then returns a count of the
number of additional lines it was supposed to move but couldn't.
`erase-buffer'
Delete the entire contents of the current buffer.
`bufferp'
Return `t' if its argument is a buffer; otherwise return `nil'.
File: emacs-lisp-intro.info, Node: optional Exercise, Prev: Second Buffer Related Review, Up: More Complex
`optional' Argument Exercise
============================
Write an interactive function with an optional argument that tests
whether its argument, a number, is greater or less than the value of
`fill-column', and tells you which, in a message. However, if you do
not pass an argument to the function, use 56 as a default value.
File: emacs-lisp-intro.info, Node: Narrowing & Widening, Next: car cdr & cons, Prev: More Complex, Up: Top
Narrowing and Widening
**********************
Narrowing is a feature of Emacs that makes it possible for you to
focus on a specific part of a buffer, and work without accidentally
changing other parts. Narrowing is normally disabled since it can
confuse novices.
* Menu:
* Narrowing advantages:: The advantages of narrowing
* save-restriction:: The `save-restriction' special form.
* what-line:: The number of the line that point is on.
* narrow Exercise::
File: emacs-lisp-intro.info, Node: Narrowing advantages, Next: save-restriction, Prev: Narrowing & Widening, Up: Narrowing & Widening
The Advantages of Narrowing
===========================
With narrowing, the rest of a buffer is made invisible, as if it
weren't there. This is an advantage if, for example, you want to
replace a word in one part of a buffer but not in another: you narrow
to the part you want and the replacement is carried out only in that
section, not in the rest of the buffer. Searches will only work within
a narrowed region, not outside of one, so if you are fixing a part of a
document, you can keep yourself from accidentally finding parts you do
not need to fix by narrowing just to the region you want. (The key
binding for `narrow-to-region' is `C-x n n'.)
However, narrowing does make the rest of the buffer invisible, which
can scare people who inadvertently invoke narrowing and think they have
deleted a part of their file. Moreover, the `undo' command (which is
usually bound to `C-x u') does not turn off narrowing (nor should it),
so people can become quite desperate if they do not know that they can
return the rest of a buffer to visibility with the `widen' command.
(The key binding for `widen' is `C-x n w'.)
Narrowing is just as useful to the Lisp interpreter as to a human.
Often, an Emacs Lisp function is designed to work on just part of a
buffer; or conversely, an Emacs Lisp function needs to work on all of a
buffer that has been narrowed. The `what-line' function, for example,
removes the narrowing from a buffer, if it has any narrowing and when
it has finished its job, restores the narrowing to what it was. On the
other hand, the `count-lines' function, which is called by `what-line',
uses narrowing to restrict itself to just that portion of the buffer in
which it is interested and then restores the previous situation.
File: emacs-lisp-intro.info, Node: save-restriction, Next: what-line, Prev: Narrowing advantages, Up: Narrowing & Widening
The `save-restriction' Special Form
===================================
In Emacs Lisp, you can use the `save-restriction' special form to
keep track of whatever narrowing is in effect, if any. When the Lisp
interpreter meets with `save-restriction', it executes the code in the
body of the `save-restriction' expression, and then undoes any changes
to narrowing that the code caused. If, for example, the buffer is
narrowed and the code that follows `save-restriction' gets rid of the
narrowing, `save-restriction' returns the buffer to its narrowed region
afterwards. In the `what-line' command, any narrowing the buffer may
have is undone by the `widen' command that immediately follows the
`save-restriction' command. Any original narrowing is restored just
before the completion of the function.
The template for a `save-restriction' expression is simple:
(save-restriction
BODY... )
The body of the `save-restriction' is one or more expressions that will
be evaluated in sequence by the Lisp interpreter.
Finally, a point to note: when you use both `save-excursion' and
`save-restriction', one right after the other, you should use
`save-excursion' outermost. If you write them in reverse order, you
may fail to record narrowing in the buffer to which Emacs switches
after calling `save-excursion'. Thus, when written together,
`save-excursion' and `save-restriction' should be written like this:
(save-excursion
(save-restriction
BODY...))
In other circumstances, when not written together, the
`save-excursion' and `save-restriction' special forms must be written
in the order appropriate to the function.
For example,
(save-restriction
(widen)
(save-excursion
BODY...))
File: emacs-lisp-intro.info, Node: what-line, Next: narrow Exercise, Prev: save-restriction, Up: Narrowing & Widening
`what-line'
===========
The `what-line' command tells you the number of the line in which
the cursor is located. The function illustrates the use of the
`save-restriction' and `save-excursion' commands. Here is the text of
the function in full:
(defun what-line ()
"Print the current line number (in the buffer) of point."
(interactive)
(save-restriction
(widen)
(save-excursion
(beginning-of-line)
(message "Line %d"
(1+ (count-lines 1 (point)))))))
The function has a documentation line and is interactive, as you
would expect. The next two lines use the functions `save-restriction'
and `widen'.
The `save-restriction' special form notes whatever narrowing is in
effect, if any, in the current buffer and restores that narrowing after
the code in the body of the `save-restriction' has been evaluated.
The `save-restriction' special form is followed by `widen'. This
function undoes any narrowing the current buffer may have had when
`what-line' was called. (The narrowing that was there is the narrowing
that `save-restriction' remembers.) This widening makes it possible
for the line counting commands to count from the beginning of the
buffer. Otherwise, they would have been limited to counting within the
accessible region. Any original narrowing is restored just before the
completion of the function by the `save-restriction' special form.
The call to `widen' is followed by `save-excursion', which saves the
location of the cursor (i.e., of point) and of the mark, and restores
them after the code in the body of the `save-excursion' uses the
`beginning-of-line' function to move point.
(Note that the `(widen)' expression comes between the
`save-restriction' and `save-excursion' special forms. When you write
the two `save- ...' expressions in sequence, write `save-excursion'
outermost.)
The last two lines of the `what-line' function are functions to
count the number of lines in the buffer and then print the number in the
echo area.
(message "Line %d"
(1+ (count-lines 1 (point)))))))
The `message' function prints a one-line message at the bottom of the
Emacs screen. The first argument is inside of quotation marks and is
printed as a string of characters. However, it may contain `%d', `%s',
or `%c' to print arguments that follow the string. `%d' prints the
argument as a decimal, so the message will say something such as `Line
243'.
The number that is printed in place of the `%d' is computed by the
last line of the function:
(1+ (count-lines 1 (point)))
What this does is count the lines from the first position of the
buffer, indicated by the `1', up to `(point)', and then add one to that
number. (The `1+' function adds one to its argument.) We add one to
it because line 2 has only one line before it, and `count-lines' counts
only the lines _before_ the current line.
After `count-lines' has done its job, and the message has been
printed in the echo area, the `save-excursion' restores point and mark
to their original positions; and `save-restriction' restores the
original narrowing, if any.
File: emacs-lisp-intro.info, Node: narrow Exercise, Prev: what-line, Up: Narrowing & Widening
Exercise with Narrowing
=======================
Write a function that will display the first 60 characters of the
current buffer, even if you have narrowed the buffer to its latter half
so that the first line is inaccessible. Restore point, mark, and
narrowing. For this exercise, you need to use `save-restriction',
`widen', `goto-char', `point-min', `buffer-substring', `message', and
other functions, a whole potpourri.
File: emacs-lisp-intro.info, Node: car cdr & cons, Next: Cutting & Storing Text, Prev: Narrowing & Widening, Up: Top
`car', `cdr', `cons': Fundamental Functions
*******************************************
In Lisp, `car', `cdr', and `cons' are fundamental functions. The
`cons' function is used to construct lists, and the `car' and `cdr'
functions are used to take them apart.
In the walk through of the `copy-region-as-kill' function, we will
see `cons' as well as two variants on `cdr', namely, `setcdr' and
`nthcdr'. (*Note copy-region-as-kill::.)
* Menu:
* Strange Names:: An historical aside: why the strange names?
* car & cdr:: Functions for extracting part of a list.
* cons:: Constructing a list.
* nthcdr:: Calling `cdr' repeatedly.
* nth::
* setcar:: Changing the first element of a list.
* setcdr:: Changing the rest of a list.
* cons Exercise::
File: emacs-lisp-intro.info, Node: Strange Names, Next: car & cdr, Prev: car cdr & cons, Up: car cdr & cons
Strange Names
=============
The name of the `cons' function is not unreasonable: it is an
abbreviation of the word `construct'. The origins of the names for
`car' and `cdr', on the other hand, are esoteric: `car' is an acronym
from the phrase `Contents of the Address part of the Register'; and
`cdr' (pronounced `could-er') is an acronym from the phrase `Contents
of the Decrement part of the Register'. These phrases refer to
specific pieces of hardware on the very early computer on which the
original Lisp was developed. Besides being obsolete, the phrases have
been completely irrelevant for more than 25 years to anyone thinking
about Lisp. Nonetheless, although a few brave scholars have begun to
use more reasonable names for these functions, the old terms are still
in use. In particular, since the terms are used in the Emacs Lisp
source code, we will use them in this introduction.
File: emacs-lisp-intro.info, Node: car & cdr, Next: cons, Prev: Strange Names, Up: car cdr & cons
`car' and `cdr'
===============
The CAR of a list is, quite simply, the first item in the list.
Thus the CAR of the list `(rose violet daisy buttercup)' is `rose'.
If you are reading this in Info in GNU Emacs, you can see this by
evaluating the following:
(car '(rose violet daisy buttercup))
After evaluating the expression, `rose' will appear in the echo area.
Clearly, a more reasonable name for the `car' function would be
`first' and this is often suggested.
`car' does not remove the first item from the list; it only reports
what it is. After `car' has been applied to a list, the list is still
the same as it was. In the jargon, `car' is `non-destructive'. This
feature turns out to be important.
The CDR of a list is the rest of the list, that is, the `cdr'
function returns the part of the list that follows the first item.
Thus, while the CAR of the list `'(rose violet daisy buttercup)' is
`rose', the rest of the list, the value returned by the `cdr' function,
is `(violet daisy buttercup)'.
You can see this by evaluating the following in the usual way:
(cdr '(rose violet daisy buttercup))
When you evaluate this, `(violet daisy buttercup)' will appear in the
echo area.
Like `car', `cdr' does not remove any elements from the list--it
just returns a report of what the second and subsequent elements are.
Incidentally, in the example, the list of flowers is quoted. If it
were not, the Lisp interpreter would try to evaluate the list by calling
`rose' as a function. In this example, we do not want to do that.
Clearly, a more reasonable name for `cdr' would be `rest'.
(There is a lesson here: when you name new functions, consider very
carefully what you are doing, since you may be stuck with the names for
far longer than you expect. The reason this document perpetuates these
names is that the Emacs Lisp source code uses them, and if I did not
use them, you would have a hard time reading the code; but do, please,
try to avoid using these terms yourself. The people who come after you
will be grateful to you.)
When `car' and `cdr' are applied to a list made up of symbols, such
as the list `(pine fir oak maple)', the element of the list returned by
the function `car' is the symbol `pine' without any parentheses around
it. `pine' is the first element in the list. However, the CDR of the
list is a list itself, `(fir oak maple)', as you can see by evaluating
the following expressions in the usual way:
(car '(pine fir oak maple))
(cdr '(pine fir oak maple))
On the other hand, in a list of lists, the first element is itself a
list. `car' returns this first element as a list. For example, the
following list contains three sub-lists, a list of carnivores, a list
of herbivores and a list of sea mammals:
(car '((lion tiger cheetah)
(gazelle antelope zebra)
(whale dolphin seal)))
In this example, the first element or CAR of the list is the list of
carnivores, `(lion tiger cheetah)', and the rest of the list is
`((gazelle antelope zebra) (whale dolphin seal))'.
(cdr '((lion tiger cheetah)
(gazelle antelope zebra)
(whale dolphin seal)))
It is worth saying again that `car' and `cdr' are
non-destructive--that is, they do not modify or change lists to which
they are applied. This is very important for how they are used.
Also, in the first chapter, in the discussion about atoms, I said
that in Lisp, "certain kinds of atom, such as an array, can be separated
into parts; but the mechanism for doing this is different from the
mechanism for splitting a list. As far as Lisp is concerned, the atoms
of a list are unsplittable." (*Note Lisp Atoms::.) The `car' and
`cdr' functions are used for splitting lists and are considered
fundamental to Lisp. Since they cannot split or gain access to the
parts of an array, an array is considered an atom. Conversely, the
other fundamental function, `cons', can put together or construct a
list, but not an array. (Arrays are handled by array-specific
functions. *Note Arrays: (elisp)Arrays.)
File: emacs-lisp-intro.info, Node: cons, Next: nthcdr, Prev: car & cdr, Up: car cdr & cons
`cons'
======
The `cons' function constructs lists; it is the inverse of `car' and
`cdr'. For example, `cons' can be used to make a four element list
from the three element list, `(fir oak maple)':
(cons 'pine '(fir oak maple))
After evaluating this list, you will see
(pine fir oak maple)
appear in the echo area. `cons' puts a new element at the beginning of
a list; it attaches or pushes elements onto the list.
* Menu:
* Build a list::
* length:: How to find the length of a list.
File: emacs-lisp-intro.info, Node: Build a list, Next: length, Prev: cons, Up: cons
Build a list
------------
`cons' must have a list to attach to.(1) You cannot start from
absolutely nothing. If you are building a list, you need to provide at
least an empty list at the beginning. Here is a series of `cons'
expressions that build up a list of flowers. If you are reading this
in Info in GNU Emacs, you can evaluate each of the expressions in the
usual way; the value is printed in this text after `=>', which you may
read as `evaluates to'.
(cons 'buttercup ())
=> (buttercup)
(cons 'daisy '(buttercup))
=> (daisy buttercup)
(cons 'violet '(daisy buttercup))
=> (violet daisy buttercup)
(cons 'rose '(violet daisy buttercup))
=> (rose violet daisy buttercup)
In the first example, the empty list is shown as `()' and a list made
up of `buttercup' followed by the empty list is constructed. As you
can see, the empty list is not shown in the list that was constructed.
All that you see is `(buttercup)'. The empty list is not counted as an
element of a list because there is nothing in an empty list. Generally
speaking, an empty list is invisible.
The second example, `(cons 'daisy '(buttercup))' constructs a new,
two element list by putting `daisy' in front of `buttercup'; and the
third example constructs a three element list by putting `violet' in
front of `daisy' and `buttercup'.
---------- Footnotes ----------
(1) Actually, you can `cons' an element to an atom to produce a
dotted pair. Dotted pairs are not discussed here; see *Note Dotted
Pair Notation: (elisp)Dotted Pair Notation.
File: emacs-lisp-intro.info, Node: length, Prev: Build a list, Up: cons
Find the Length of a List: `length'
-----------------------------------
You can find out how many elements there are in a list by using the
Lisp function `length', as in the following examples:
(length '(buttercup))
=> 1
(length '(daisy buttercup))
=> 2
(length (cons 'violet '(daisy buttercup)))
=> 3
In the third example, the `cons' function is used to construct a three
element list which is then passed to the `length' function as its
argument.
We can also use `length' to count the number of elements in an empty
list:
(length ())
=> 0
As you would expect, the number of elements in an empty list is zero.
An interesting experiment is to find out what happens if you try to
find the length of no list at all; that is, if you try to call `length'
without giving it an argument, not even an empty list:
(length )
What you see, if you evaluate this, is the error message
Wrong number of arguments: #<subr length>, 0
This means that the function receives the wrong number of arguments,
zero, when it expects some other number of arguments. In this case,
one argument is expected, the argument being a list whose length the
function is measuring. (Note that _one_ list is _one_ argument, even
if the list has many elements inside it.)
The part of the error message that says `#<subr length>' is the name
of the function. This is written with a special notation, `#<subr',
that indicates that the function `length' is one of the primitive
functions written in C rather than in Emacs Lisp. (`subr' is an
abbreviation for `subroutine'.) *Note What Is a Function?: (elisp)What
Is a Function, for more about subroutines.
File: emacs-lisp-intro.info, Node: nthcdr, Next: nth, Prev: cons, Up: car cdr & cons
`nthcdr'
========
The `nthcdr' function is associated with the `cdr' function. What
it does is take the CDR of a list repeatedly.
If you take the CDR of the list `(pine fir oak maple)', you will be
returned the list `(fir oak maple)'. If you repeat this on what was
returned, you will be returned the list `(oak maple)'. (Of course,
repeated CDRing on the original list will just give you the original
CDR since the function does not change the list. You need to evaluate
the CDR of the CDR and so on.) If you continue this, eventually you
will be returned an empty list, which in this case, instead of being
shown as `()' is shown as `nil'.
For review, here is a series of repeated CDRs, the text following
the `=>' shows what is returned.
(cdr '(pine fir oak maple))
=>(fir oak maple)
(cdr '(fir oak maple))
=> (oak maple)
(cdr '(oak maple))
=>(maple)
(cdr '(maple))
=> nil
(cdr 'nil)
=> nil
(cdr ())
=> nil
You can also do several CDRs without printing the values in between,
like this:
(cdr (cdr '(pine fir oak maple)))
=> (oak maple)
In this example, the Lisp interpreter evaluates the innermost list
first. The innermost list is quoted, so it just passes the list as it
is to the innermost `cdr'. This `cdr' passes a list made up of the
second and subsequent elements of the list to the outermost `cdr',
which produces a list composed of the third and subsequent elements of
the original list. In this example, the `cdr' function is repeated and
returns a list that consists of the original list without its first two
elements.
The `nthcdr' function does the same as repeating the call to `cdr'.
In the following example, the argument 2 is passed to the function
`nthcdr', along with the list, and the value returned is the list
without its first two items, which is exactly the same as repeating
`cdr' twice on the list:
(nthcdr 2 '(pine fir oak maple))
=> (oak maple)
Using the original four element list, we can see what happens when
various numeric arguments are passed to `nthcdr', including 0, 1, and 5:
;; Leave the list as it was.
(nthcdr 0 '(pine fir oak maple))
=> (pine fir oak maple)
;; Return a copy without the first element.
(nthcdr 1 '(pine fir oak maple))
=> (fir oak maple)
;; Return a copy of the list without three elements.
(nthcdr 3 '(pine fir oak maple))
=> (maple)
;; Return a copy lacking all four elements.
(nthcdr 4 '(pine fir oak maple))
=> nil
;; Return a copy lacking all elements.
(nthcdr 5 '(pine fir oak maple))
=> nil
File: emacs-lisp-intro.info, Node: nth, Next: setcar, Prev: nthcdr, Up: car cdr & cons
`nth'
=====
The `nthcdr' function takes the CDR of a list repeatedly. The `nth'
function takes the CAR of the result returned by `nthcdr'. It returns
the Nth element of the list.
Thus, if it were not defined in C for speed, the definition of `nth'
would be:
(defun nth (n list)
"Returns the Nth element of LIST.
N counts from zero. If LIST is not that long, nil is returned."
(car (nthcdr n list)))
(Originally, `nth' was defined in Emacs Lisp in `subr.el', but its
definition was redone in C in the 1980s.)
The `nth' function returns a single element of a list. This can be
very convenient.
Note that the elements are numbered from zero, not one. That is to
say, the first element of a list, its CAR is the zeroth element. This
is called `zero-based' counting and often bothers people who are
accustomed to the first element in a list being number one, which is
`one-based'.
For example:
(nth 0 '("one" "two" "three"))
=> "one"
(nth 1 '("one" "two" "three"))
=> "two"
It is worth mentioning that `nth', like `nthcdr' and `cdr', does not
change the original list--the function is non-destructive. This is in
sharp contrast to the `setcar' and `setcdr' functions.
File: emacs-lisp-intro.info, Node: setcar, Next: setcdr, Prev: nth, Up: car cdr & cons
`setcar'
========
As you might guess from their names, the `setcar' and `setcdr'
functions set the CAR or the CDR of a list to a new value. They
actually change the original list, unlike `car' and `cdr' which leave
the original list as it was. One way to find out how this works is to
experiment. We will start with the `setcar' function.
First, we can make a list and then set the value of a variable to the
list, using the `setq' function. Here is a list of animals:
(setq animals '(antelope giraffe lion tiger))
If you are reading this in Info inside of GNU Emacs, you can evaluate
this expression in the usual fashion, by positioning the cursor after
the expression and typing `C-x C-e'. (I'm doing this right here as I
write this. This is one of the advantages of having the interpreter
built into the computing environment.)
When we evaluate the variable `animals', we see that it is bound to
the list `(antelope giraffe lion tiger)':
animals
=> (antelope giraffe lion tiger)
Put another way, the variable `animals' points to the list `(antelope
giraffe lion tiger)'.
Next, evaluate the function `setcar' while passing it two arguments,
the variable `animals' and the quoted symbol `hippopotamus'; this is
done by writing the three element list `(setcar animals 'hippopotamus)'
and then evaluating it in the usual fashion:
(setcar animals 'hippopotamus)
After evaluating this expression, evaluate the variable `animals'
again. You will see that the list of animals has changed:
animals
=> (hippopotamus giraffe lion tiger)
The first element on the list, `antelope' is replaced by `hippopotamus'.
So we can see that `setcar' did not add a new element to the list as
`cons' would have; it replaced `giraffe' with `hippopotamus'; it
_changed_ the list.
File: emacs-lisp-intro.info, Node: setcdr, Next: cons Exercise, Prev: setcar, Up: car cdr & cons
`setcdr'
========
The `setcdr' function is similar to the `setcar' function, except
that the function replaces the second and subsequent elements of a list
rather than the first element.
To see how this works, set the value of the variable to a list of
domesticated animals by evaluating the following expression:
(setq domesticated-animals '(horse cow sheep goat))
If you now evaluate the list, you will be returned the list `(horse cow
sheep goat)':
domesticated-animals
=> (horse cow sheep goat)
Next, evaluate `setcdr' with two arguments, the name of the variable
which has a list as its value, and the list to which the CDR of the
first list will be set;
(setcdr domesticated-animals '(cat dog))
If you evaluate this expression, the list `(cat dog)' will appear in
the echo area. This is the value returned by the function. The result
we are interested in is the "side effect", which we can see by
evaluating the variable `domesticated-animals':
domesticated-animals
=> (horse cat dog)
Indeed, the list is changed from `(horse cow sheep goat)' to `(horse
cat dog)'. The CDR of the list is changed from `(cow sheep goat)' to
`(cat dog)'.
File: emacs-lisp-intro.info, Node: cons Exercise, Prev: setcdr, Up: car cdr & cons
Exercise
========
Construct a list of four birds by evaluating several expressions with
`cons'. Find out what happens when you `cons' a list onto itself.
Replace the first element of the list of four birds with a fish.
Replace the rest of that list with a list of other fish.